package com.example.latch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

/***
 *
 * 基于共享文件的形式实现主从
 */
public class FileLeaderLatch implements LeaderLatch {

    Logger logger = LoggerFactory.getLogger(getClass());

    public String path;

    private FileChannel fileChannel;

    private FileLock lock;

    private RandomAccessFile file;

    private volatile boolean isStop = false;

    private LeaderLatchListener leaderLatchListener;

    private Thread thread;

    public FileLeaderLatch(String path, LeaderLatchListener leaderLatchListener) {
        this.path = path;
        this.leaderLatchListener = leaderLatchListener;
    }

    @Override
    public void lock() {
        this.thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!isStop) {
                    try {
                        file = new RandomAccessFile(path, "rw");
                        fileChannel = file.getChannel();
                        lock = fileChannel.lock();
                        break;
                    } catch (Exception e) {
                        logger.warn("get lock error :" + e.getMessage());
                    } finally {
                        if (lock == null) {
                            logger.warn("lock lock ...");
                        }
                    }
                }
                leaderLatchListener.isMaster();
            }
        });
        this.thread.start();
    }

    @Override
    public void unlock() {
        isStop = true;
        if (lock != null) {
            try {
                lock.release();
            } catch (IOException e) {
                logger.warn("lock release error :" + e.getMessage());
            }
        }
        if (fileChannel != null) {
            try {
                fileChannel.close();
            } catch (IOException e) {
                logger.warn("fileChannel close error :" + e.getMessage());
            }
        }
        if (file != null) {
            try {
                file.close();
            } catch (IOException e) {
                logger.warn("fileOutputStream close error :" + e.getMessage());
            }
        }
        if (this.thread.isAlive()) {
            this.thread.interrupt();
        }
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public FileChannel getFileChannel() {
        return fileChannel;
    }

    public void setFileChannel(FileChannel fileChannel) {
        this.fileChannel = fileChannel;
    }

    public FileLock getLock() {
        return lock;
    }

    public void setLock(FileLock lock) {
        this.lock = lock;
    }

    public RandomAccessFile getFile() {
        return file;
    }

    public void setFile(RandomAccessFile file) {
        this.file = file;
    }

    public boolean isStop() {
        return isStop;
    }

    public void setStop(boolean stop) {
        isStop = stop;
    }

    public LeaderLatchListener getLeaderLatchListener() {
        return leaderLatchListener;
    }

    public void setLeaderLatchListener(LeaderLatchListener leaderLatchListener) {
        this.leaderLatchListener = leaderLatchListener;
    }
}
